package cn.ciis.basic.base;

import cn.ciis.basic.kit.CiisKit;
import cn.ciis.basic.kit.ImageKit;
import cn.ciis.basic.model.Account;
import cn.ciis.sys.account.AccountAdminService;
import cn.ciis.sys.login.LoginService;
import cn.hutool.core.convert.Convert;
import cn.hutool.poi.excel.ExcelReader;
import cn.hutool.poi.excel.ExcelUtil;
import com.cybermkd.mongo.kit.MongoQuery;
import com.cybermkd.mongo.kit.page.MongoPage;
import com.cybermkd.mongo.kit.page.MongoPaginate;
import com.jfinal.aop.Aop;
import com.jfinal.core.Controller;
import com.jfinal.core.NotAction;
import com.jfinal.kit.PathKit;
import com.jfinal.kit.Ret;
import com.jfinal.plugin.activerecord.Db;
import com.jfinal.plugin.activerecord.Model;
import com.jfinal.plugin.activerecord.Page;
import com.jfinal.plugin.activerecord.Record;
import com.jfinal.upload.UploadFile;

import java.awt.image.BufferedImage;
import java.io.File;
import java.util.List;
import java.util.Map;

/**
 * @author 冉志林
 */
public class BaseController extends Controller {

    private Account loginAccount = null;

    AccountAdminService accountAdminService = Aop.get(AccountAdminService.class);

    @Override
    protected void _clear_() {
        loginAccount = null;
        super._clear_();
    }

    @NotAction
    public Account getLoginAccount() {
        if (loginAccount == null) {
            loginAccount = getAttr(LoginService.LOGIN_ACCOUNT_CACHE_NAME);
            if (loginAccount != null && !loginAccount.isStatusOk()) {
                throw new IllegalStateException("当前用户状态不允许登录，status = " + loginAccount.getStatus());
            }
        }
        return loginAccount;
    }

    @NotAction
    public List<Account> getAccountListInfo() {
        return accountAdminService.getListAccount();
    }

    @NotAction
    public boolean isLogin() {
        return getLoginAccount() != null;
    }

    @NotAction
    public boolean notLogin() {
        return !isLogin();
    }

    /**
     * 获取登录账户id 确保在 FrontAuthInterceptor 之下使用，或者 isLogin() 为 true 时使用 也即确定已经是在登录后才可调用
     */
    @NotAction
    public int getLoginAccountId() {
        return getLoginAccount().getId();
    }

    /**
     * 是否为超级管理员
     *
     * @return
     */
    @NotAction
    public boolean isSuperAdmin() {
        int loginAccountId = getLoginAccountId();
        return loginAccountId == 1;
    }

    @NotAction
    public void kIndex() {
        render("index.html");
    }

    @SuppressWarnings("rawtypes")
    @NotAction
    public void kAddOrEdit(Model model) {
        keepPara("p");
        keepPara("s");
        if (null != model) {
            set("model", model);
        }
        set("accountList", getAccountListInfo());
        render("add_edit.html");
    }

    public static final String PAGE = "page";
    public static final String MODEL = "model";
    public static final String PAGENUMBER = "p";
    public static final String PAGESIZE = "s";

    @NotAction
    public void kModel(Model<?> model, Page<?> paginate) {
        keepPara();
        set(MODEL, model).set(PAGE, paginate);
    }

    @NotAction
    public void kModel(Model<?> model, Page<?> paginate, String view) {
        keepPara();
        set(MODEL, model).set(PAGE, paginate);
        render(view + ".html");
    }

    @NotAction
    public void kRecord(Record record, Page<?> paginate) {
        keepPara();
        set("record", record).set(PAGE, paginate);
        kIndex();
    }

    @NotAction
    public void kSuccess() {
        renderJson(Ret.ok("msg", "操作成功"));
    }

    @NotAction
    public void kSuccess(Ret ret) {
        renderJson(Ret.ok("msg", "操作成功").set("data", ret));
    }

    @NotAction
    public void kSuccess(Model<?> model) {
        renderJson(Ret.ok("msg", "操作成功").set("data", model));
    }

    @NotAction
    public void kSuccess(List<?> list) {
        renderJson(Ret.ok("msg", "操作成功").set("data", list));
    }

    @NotAction
    public void kSuccess(String msg) {
        renderJson(Ret.ok("msg", msg));
    }

    @NotAction
    public void kFail() {
        renderJson(Ret.fail("msg", "系统错误"));
    }

    @NotAction
    public void kFail(String msg) {
        renderJson(Ret.fail("msg", msg));
    }

    public void kRenderJson(boolean b) {
        renderJson(b ? Ret.ok("msg", "操作成功") : Ret.fail("msg", "操作失败"));
    }

    /**
     * 使用循环判断 （效率最高）
     */
    @NotAction
    public static boolean useLoop(String[] arr, String targetValue) {
        for (String s : arr) {
            if (s.equals(targetValue)) {
                return true;
            }
        }
        return false;
    }


    /*excel文件下载*/
    @NotAction
    public void kDownLoad(String fileName) {
        File file =
                new File(
                        PathKit.getWebRootPath()
                                + File.separator
                                + "download"
                                + File.separator
                                + "export"
                                + File.separator
                                + fileName);
        if (file.isFile()) {
            renderFile(file);
        }

    }

    /**
     * excel导入
     *
     * @param tableName
     * @param rd
     */
    @NotAction
    public void kImport(String tableName, Record... rd) {
        String fileUrl = getFileUrl();
        ExcelReader reader = ExcelUtil.getReader(fileUrl);
        List<Object> objects = reader.readRow(0);
        String[] importFieldSplit = CiisKit.getImportProperties().get(tableName).split(",");
        if (objects.size() != importFieldSplit.length) {
            kFail("文件格式有问题，请重新下载模板文件填写后再尝试上传");
            return;
        }
        for (int i = 0; i < objects.size(); i++) {
            reader.addHeaderAlias(objects.get(i).toString(), importFieldSplit[i]);
        }

        List<Map<String, Object>> listMap = reader.readAll();
        for (Map<String, Object> aa : listMap) {
            Record record = new Record();
            for (String s : aa.keySet()) {
                record.set(s, aa.get(s));
            }
            if (rd != null) {
                for (Record record1 : rd) {

                    record.setColumns(record1);
                }
            }
            Db.save(tableName, record);
        }
        File file1 = new File(fileUrl);
        boolean delete = file1.delete();
        if (delete) {
            kSuccess("文件导入成功");
        }
    }

    /**
     * 文件消息返回
     *
     * @param file
     */
    @NotAction
    public void kFile(File file) {
        if (file.isFile()) {
            kSuccess(new Ret().set("fileName", file.getName()));
        } else {
            kFail();
        }
    }

    /**
     * 文件上传时候需要的文件路径
     *
     * @return
     */
    @NotAction
    public String getFileUrl() {
        UploadFile file = getFile();
        return file.getUploadPath() + File.separator + file.getFileName();
    }


    /**
     * 图片上传
     * @param parameterName  接收的参数名称
     * @param uploadPath    保存路径  upload后面的路径
     * @param maxSize   最大容量
     * @param maxWidth  最大宽度
     */
    public void kUploadFile(String parameterName, String uploadPath, int maxSize, int maxWidth) {
        Ret ret = null;
        UploadFile uf = null;
        try {
            uf = getFile(parameterName, uploadPath + "/temp", maxSize);
            if (uf == null) {
                kFail("请先选择上传文件");
                return;
            }
            if (cn.ciis.basic.kit.ImageKit.notImageExtName(uf.getFileName())) {
                kFail("文件类型不正确，只支持图片类型：gif、jpg、jpeg、png、bmp");
                return;
            }
            String imgUrl ="/upload/"+uploadPath+"/temp/" + System.currentTimeMillis() + ".jpg";
            // File.separator 兼容性
            cn.ciis.basic.kit.ImageKit.zoom(maxWidth, uf.getFile(), PathKit.getWebRootPath()+imgUrl);
            ret = Ret.ok("dir",imgUrl);
        } catch (Exception e) {
            if (e instanceof com.jfinal.upload.ExceededSizeException) {
                kFail("文件大小超出范围");
                return;
            } else {
                kFail(e.getMessage());
            }
            return;
        }finally {
            uf.getFile().delete();
        }
        // 上传成功则将文件 url 径暂存起来，供下个环节进行裁切
        if (ret.isOk()) {
            setSessionAttr("dir", ret.get("dir"));
        }
        renderJson(ret);
    }

    /**
     * 图片裁剪保存
     * @param model 实体类
     * @param imgPath   图片存放的文件夹名称
     * @param tableName 需要操作表的名称
     * @param filedName 存储图片路径的字段名称
     */
    public void kSaveImg(Model<?> model,String imgPath,String tableName,String filedName,String...name){
        String dirUrl = getSessionAttr("dir");
        Integer x = getParaToInt("x");
        Integer y = getParaToInt("y");
        Integer width = getParaToInt("width");
        Integer height = getParaToInt("height");
        int id = model.getInt("id");
        String avatarFileName = PathKit.getWebRootPath() + dirUrl;
        try {
            // 相对路径 + 文件名：用于保存到 account.avatar 字段
            String[] relativePathFileName = new String[1];
            // 绝对路径 + 文件名：用于保存到文件系统
            String[] absolutePathFileName = new String[1];

            String relativePath = (id / 5000) + "/";
            String fileName = id + ".jpg";
            if (name.length>0){
                fileName=model.getStr(name[0]).replace(".","")+ ".jpg";
            }
            relativePathFileName[0] = relativePath + fileName;

            String absolutePath = PathKit.getWebRootPath() + "/upload/"+imgPath+"/" + relativePath;
            File temp = new File(absolutePath);
            if (!temp.exists()) {
                temp.mkdirs(); // 如果目录不存在则创建
            }
            absolutePathFileName[0] = absolutePath + fileName;

            BufferedImage bi = cn.ciis.basic.kit.ImageKit.crop(avatarFileName, x, y, width, height);
            // 将 size 变为 200 X 200，resize 不会变改分辨率
            bi = cn.ciis.basic.kit.ImageKit.resize(bi, 200, 200);
            //deleteOldAvatarIfExists(absolutePathFileName[0]);
            ImageKit.save(bi, absolutePathFileName[0]);

            Db.update("update "+tableName+" set "+filedName+"=? where id=? limit 1", relativePathFileName[0], id);
            kSuccess("图像更新成功，部分浏览器需要按 CTRL + F5 强制刷新看效果");
        }catch (Exception e){
            kFail("图像更新失败：" + e.getMessage());
        } finally {
            new File(avatarFileName).delete(); // 删除用于裁切的源文件
        }
        kSuccess(model);
    }

    /**
     * mongo分页查询
     * @param tableInfo
     */
    public void mongoPage(String tableInfo){
        MongoQuery mongoQuery = new MongoQuery();
        mongoQuery.use(tableInfo).descending("create_time");
        MongoPaginate page=new MongoPaginate(mongoQuery,getInt(PAGESIZE, 10),getInt(PAGENUMBER, 1));
        MongoPage mongoPage = page.findAll();
        Page<Record> result_page = new Page<>();
        result_page.setList(mongoPage.getList());
        result_page.setPageNumber(getInt(PAGENUMBER, 1));
        result_page.setPageSize(mongoPage.getCount());
        result_page.setTotalPage(mongoPage.getTotalPage());
        result_page.setTotalRow(Convert.toInt(mongoPage.getTotalRow()));
        set(PAGE,result_page);
    }
}
